package mastermind.net;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;

import mastermind.net.Protocol.OpCode;

/** Wrapper for MM client/server communications */
public class GameStream {

	public DataInputStream in;
	public DataOutputStream out;
	public ObjectInputStream oin;
	public ObjectOutputStream oout;

	/** Initialise streams from a Socket connection */
	public GameStream(Socket s) throws IOException {
		out = new DataOutputStream(s.getOutputStream());
		in = new DataInputStream(s.getInputStream());

		oout = new ObjectOutputStream(s.getOutputStream());
		oin = new ObjectInputStream(s.getInputStream());
	}

	/**
	 * Read an OpCode stream
	 * 
	 * @return Received OpCode, may be UNRECOGNIZED_OPERATION
	 * @throws IOException
	 */
	public OpCode readOpCode() throws IOException {
		int ordinal = in.readInt();
		return (ordinal < OpCode.values().length) ? OpCode.values()[ordinal]
				: OpCode.UNRECOGNISED_OPERATION;
	}

	/**
	 * Write an OpCode to stream
	 * 
	 * @param op
	 *            OpCode to send
	 * @throws IOException
	 */
	public void sendOpCode(OpCode op) throws IOException {
		out.writeInt(op.ordinal());
	}

	/**
	 * Writes an object to stream
	 * 
	 * @param o
	 *            Serializable object to write
	 * @throws IOException
	 */
	public void writeObject(Serializable o) throws IOException {
		oout.writeObject(o);
	}

	/**
	 * Reads an object from stream
	 * 
	 * @return Received object
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public Object readObject() throws IOException, ClassNotFoundException {
		return oin.readObject();
	}

	/**
	 * Closes all streams
	 * 
	 * @throws IOException
	 */
	public void closeAll() throws IOException {
		in.close();
		out.close();
		oin.close();
		oout.close();
	}
}
